package com.team.databoard.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.team.databoard.common.BaseResponse;
import com.team.databoard.common.ErrorCode;
import com.team.databoard.common.ResultUtils;
import com.team.databoard.exception.BusinessException;
import com.team.databoard.model.Student;
import com.team.databoard.service.StudentService;
import com.team.databoard.util.VerifyUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

import static com.team.databoard.constant.UserConstant.USER_LOGIN_STATE;

@RestController
public class ExcelController {
    @Resource
    private StudentService studentService;

    private static final String FILE_NAME = "student.xlsx";

    @GetMapping("/template")
    public void downloadTemplate(HttpServletResponse response) {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + FILE_NAME);
        try {
            EasyExcel.write(response.getOutputStream(), Student.class).sheet("学生信息").doWrite(ListUtils.newArrayList());
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "获取模板失败");
        }
    }

    @PostMapping("/upload")
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse<Boolean> upload(MultipartFile file, HttpServletRequest request) {
        if (request.getSession().getAttribute(USER_LOGIN_STATE) == null) {
            return ResultUtils.error(ErrorCode.NOT_LOGIN);
        }
        try {
            EasyExcel.read(file.getInputStream(), Student.class, new ReadListener<Student>() {
                /**
                 * 单次缓存的数据量
                 */
                public static final int BATCH_COUNT = 100;
                /**
                 *临时存储
                 */
                private final List<Student> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

                /**
                 * 读取每一行数据
                 * @param data 行数据
                 * @param context 上下文
                 */
                @Override
                public void invoke(Student data, AnalysisContext context) {
                    if (VerifyUtils.isStudentValid(data)) {
                        cachedDataList.add(data);
                    } else {
                        throw new BusinessException(ErrorCode.IMPORT_ERROR, String.format("第%d行数据格式错误", context.readRowHolder().getRowIndex() + 1));
                    }
                    // 达到缓存数量后，批量存储
                    if (cachedDataList.size() >= BATCH_COUNT) {
                        studentService.saveBatch(cachedDataList);
                        cachedDataList.clear();
                    }
                }

                /**
                 * 读取完所有数据后的操作
                 * @param context 上下文
                 */
                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                    studentService.saveBatch(cachedDataList);
                }
            }).sheet().doRead();
            return ResultUtils.success(true);
        } catch (BusinessException e) {
            throw new BusinessException(ErrorCode.IMPORT_ERROR, e.getDescription());
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
    }
}
